package com.project.web.controller.login;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.project.entity.sys.Role;
import com.project.security.SecurityRealm;
import com.project.service.sys.UserService;
import com.project.util.EncryptString;
import com.project.util.VerifyCodeUtil;

@Controller
@RequestMapping("/login")
public class LoginController {
	
	private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
	
	@Autowired
	private EncryptString encryptString;
	@Autowired
	private UserService userService;
	
	/**
	 * 登录init
	 * @param model
	 * @param request
	 * @return
	 */
	@RequestMapping(value="init",method=RequestMethod.GET)
	public String init(Model model,HttpServletRequest request){
		String messageLogin = request.getParameter("message_login");
		model.addAttribute("message_login", messageLogin);
		return "/login/login";
	}

	/**
	 * 登录
	 * @param model
	 * @return
	 */
	@RequestMapping(value="login")
	public String login(Model model,HttpServletRequest request){
		String resultPageURL = "redirect:/login/init";  
        String username = request.getParameter("username");  
        String password = request.getParameter("password");
        //获取HttpSession中的验证码  
        String verifyCode = (String)request.getSession().getAttribute("verifyCode");  
        //获取用户请求表单中输入的验证码  
        String submitCode = WebUtils.getCleanParam(request, "verifyCode");  
//        System.out.println("用户[" + username + "]登录时输入的验证码为[" + submitCode + "],HttpSession中的验证码为[" + verifyCode + "]");  
        if (StringUtils.isEmpty(submitCode) || !StringUtils.equals(verifyCode, submitCode.toLowerCase())){  
        	model.addAttribute("message_login", "验证码不正确");  
            return resultPageURL;  
        }
        
        if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
        	model.addAttribute("message_login", "用户名和密码不能为空");  
            return resultPageURL;
        }
        UsernamePasswordToken token = new UsernamePasswordToken(username, encryptString.MD5Encrypt(password));  
        token.setRememberMe(true);  
//      System.out.println("为了验证登录用户而封装的token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));  
        //获取当前的Subject  
        Subject currentUser = SecurityUtils.getSubject();  
        SecurityUtils.getSecurityManager();
        
        try {  
            currentUser.login(token);
            resultPageURL = "redirect:/home/home?menuUrlSign=1";
            List<Role> roles = userService.getRolsByUserCode(username);
            SecurityRealm.roleMap.put(username, roles);
        }catch(UnknownAccountException uae){ 
        	model.addAttribute("message_login", "账号不存在");  
        }catch(IncorrectCredentialsException ice){  
        	model.addAttribute("message_login", "密码错误");  
        }catch(LockedAccountException lae){  
        	model.addAttribute("message_login", "账户未启用");  
        }catch(ExcessiveAttemptsException eae){
        	model.addAttribute("message_login", "用户名或密码错误次数过多");  
        }catch(AuthenticationException ae){  
            //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景  
            //System.out.println("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");  
            ae.printStackTrace();  
            model.addAttribute("message_login", "用户名或密码不正确");  
        }  
        //验证是否登录成功  
        if(currentUser.isAuthenticated()){  
        	logger.info("用户:"+username+"登录");
//        	return "redirect:/home/home?menuUrlSign=1";
        }else{  
            token.clear();  
        }  
        return resultPageURL;

	}
	
	/** 
     * 获取验证码图片和文本(验证码文本会保存在HttpSession中) 
     */  
    @RequestMapping("/getVerifyCodeImage")  
    public void getVerifyCodeImage(HttpServletRequest request, HttpServletResponse response) throws IOException {  
        //设置页面不缓存  
        response.setHeader("Pragma", "no-cache");  
        response.setHeader("Cache-Control", "no-cache");  
        response.setDateHeader("Expires", 0);  
        String verifyCode = VerifyCodeUtil.generateTextCode(VerifyCodeUtil.TYPE_NUM_ONLY, 4, null);  
        //将验证码放到HttpSession里面  
        request.getSession().setAttribute("verifyCode", verifyCode);  
//        System.out.println("本次生成的验证码为[" + verifyCode + "],已存放到HttpSession中");  
        //设置输出的内容的类型为JPEG图像  
        response.setContentType("image/jpeg");  
        BufferedImage bufferedImage = VerifyCodeUtil.generateImageCode(verifyCode, 90, 30, 3, true, Color.WHITE, Color.BLACK, null);  
        //写给浏览器  
        ImageIO.write(bufferedImage, "JPEG", response.getOutputStream());  
    }  

    /** 
     * 用户登出 
     */  
    @RequestMapping("/logout")  
    public String logout(HttpServletRequest request){  
         SecurityUtils.getSubject().logout();  
         return InternalResourceViewResolver.REDIRECT_URL_PREFIX + "/";  
    } 

    @RequestMapping("/403")  
	public String e403(){
		return "/common/403";
	}
    
    @RequestMapping("/404")  
	public String e404(){
		return "/common/404";
	}
    
    @RequestMapping("/500")  
	public String e500(){
		return "/common/500";
	}
	
	@RequestMapping("/unauthorized")  
	public String unauthorized(){
		return "/common/unauthorized";
	}
}
